package com.hjxr.quota.sdoc.service.impl;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjxr.quota.sdoc.domain.Sdoc;
import com.hjxr.quota.sdoc.domain.SdocColname;
import com.hjxr.quota.sdoc.mapper.FileOperationMapper;
import com.hjxr.quota.sdoc.mapper.SdocColnameMapper;
import com.hjxr.quota.sdoc.mapper.SdocMapper;
import com.hjxr.quota.sdoc.service.FileOperationService;
import com.hjxr.quota.sdoc.service.SdocColnameService;
import com.hjxr.quota.util.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ma
 * @date 2020/9/4 - 11:34
 **/
@Service
public class FileOperationServiceImpl extends ServiceImpl<SdocColnameMapper, SdocColname> implements FileOperationService {
    @Resource
    private FileOperationMapper fileOperationMapper;
    @Resource
    private SdocMapper sdocMapper;
    @Resource
    private SdocColnameMapper sdocColnameMapper;
    @Autowired
    private SdocColnameService sdocColnameService;
    @Value("${hjxr.profile}")
    private String proFilePath;

    @Override
    public String fileUpload(MultipartFile file) {
        if (file.isEmpty()) {
            return "文件不存在";
        }
        try {
            InputStream inputStream = file.getInputStream();
            String fileName = file.getOriginalFilename();
            String finalName = System.currentTimeMillis() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
            File dest = new File(proFilePath + "//" + finalName);
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(dest);
            } catch (Exception e) {
                e.printStackTrace();
                return e.toString();
            }

            return finalName;

        } catch (IOException e) {
            e.printStackTrace();
            return e.toString();
        }
    }



    @Override
    public Boolean fileToDb(Integer id) throws Exception {
        Map<String, Object> maps = new HashMap<String, Object>();
        List<String> allFieldsList = new ArrayList<>();//选取字段列表
        List<String> allTitleList = new ArrayList<>();//全部文件头列表
        List<Integer> fieldIndex = new ArrayList<>();//字段下标列表
        List<String> fields = new ArrayList<>();//已选的文件头名称
        List<String> fieldCode = new ArrayList<>();//已选的文件头代码

        String tableName = sdocMapper.selectById(id).getDocTableCode();//获得表名
        maps.put("tablename", tableName);//添加表名到map
        maps.put("seqname", "SEQ_" + tableName);//添加表名到map


        List<SdocColname> sdocColnameList = sdocColnameService.getListByDocId(id);
        for (SdocColname s : sdocColnameList) {//获得已选的文件头列表
            fields.add(s.getColumnName());
            fieldCode.add(s.getColumnCode());
        }
        maps.put("fields", fieldCode);

        String path = sdocMapper.selectById(id).getDocUrl();//获取文件地址
        String fileType = sdocMapper.selectById(id).getDocType();//判断文件类型
        try {
            if (fileType.equalsIgnoreCase("csv") || fileType.equalsIgnoreCase("txt")) {//文件类型为txt/csv
                BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
                String firstline = reader.readLine();
                for (String a : firstline.split(",")
                ) {
                    allTitleList.add(a);
                }//获取文件全部头字段
                for (String field : fields) {//遍历已选文件头字段
                    fieldIndex.add(allTitleList.indexOf(field));
                }
                String line = null;
                while ((line = reader.readLine()) != null) {
                    String[] allFields = line.split(",",-1);
                    for (Integer i : fieldIndex) {
                        //判断字段值首尾是否带双引号
                        if(allFields[i].startsWith("\"")&&allFields[i].endsWith("\"")){
                            allFields[i] = allFields[i].substring(1,allFields[i].length());   //去掉第一个 "
                            allFields[i] = allFields[i].substring(0,allFields[i].length()-1);  //去掉最后一个 "
                        }
                        //存入
                        allFieldsList.add(allFields[i]);
                    }
                    maps.put("values", allFieldsList);
                    fileOperationMapper.FileInsertToDb(maps);

                    allFieldsList.clear();
                }


            } else {  //文件类型为excel
                List<List<String>> lists = FileUtils.readExcelRow(path, allFieldsList, allTitleList, fieldIndex, fields);
                for (List<String> list1 : lists) {
                    List<String> finalList=new ArrayList<>();
                    //字段值处理
                    for (String str:list1) {
                        //判断字段值首尾是否带双引号
                        if(str.startsWith("\"")&&str.endsWith("\"")){
                            str = str.substring(1,str.length());   //去掉第一个 "
                            str = str.substring(0,str.length()-1);  //去掉最后一个 "
                        }
                        finalList.add(str);
                    }
                    maps.put("values", finalList);
                    fileOperationMapper.FileInsertToDb(maps);
                }
            }
            //导入成功，修改文件表导入数据标识
            Sdoc sdoc = new Sdoc();
            sdoc.setId(id);
            sdoc.setIsExistData(1);
            sdocMapper.updateById(sdoc);
            return true;

        } catch (IOException e) {
            e.printStackTrace();
            return false;

        }
    }

    @Override
    public Integer checkTableExist(String tableName) {
        return fileOperationMapper.checkTableExist(tableName);
    }

    @Override
    public Integer createTableByFileInform(Integer docId) {
        Boolean isUpdateTablename = false;
        Map maps = new HashMap();
        maps.put("id", docId);
        List<String> lists = new ArrayList<>();
        lists.add("id number primary key");
        try {
            Sdoc sdoc = sdocMapper.selectById(docId);
            String tableName = sdocMapper.selectById(docId).getDocTableCode();
            while (checkTableExist(tableName) > 0) {
                isUpdateTablename = true;
                tableName = tableName + "_x";
                if (checkTableExist(tableName) == 0)
                    break;
            }
            maps.put("tablename", tableName);//得到不重复得表名

            QueryWrapper<SdocColname> wrapper = new QueryWrapper<>();
            wrapper.eq("DOC_ID", docId);
            List<SdocColname> list = this.list(wrapper);
            for (SdocColname s : list) {

                if (s.getColumnLength().isEmpty()) {
                    lists.add(s.getColumnCode() + " " + s.getDataType());
                }
                String str = s.getColumnCode() + " " + s.getDataType() + "(" + s.getColumnLength() + ")";
                lists.add(str);
            }
            maps.put("fieldList", lists);
            if (sdocMapper.selectById(docId).getIsExistTable() == 0) {
                fileOperationMapper.createTable(maps);
                Sdoc sdoc1 = new Sdoc();
                sdoc1.setId(docId);
                sdoc1.setIsExistTable(1);
                if (isUpdateTablename) {
                    sdoc1.setDocTableCode(tableName);
                }
                sdocMapper.updateById(sdoc1);
                if (fileOperationMapper.checkSequence("SEQ_" + tableName) == 0) {
                    fileOperationMapper.createSequence("SEQ_" + tableName);
                }
                return 1;
            } else {
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 0;

        }

    }

    @Override
    public Map<String, Object> checkDataLength(Integer id) {
        /**
         * 暂时写在一坨 分工具类方法好看些
         * */
        Map<String, Object> resultMap = new HashMap<>();
        Sdoc sdoc = sdocMapper.selectById(id);

        String docUrl = sdoc.getDocUrl();
        String docType = sdoc.getDocType();
        int line = 0;
        BufferedReader in = null;

        QueryWrapper<SdocColname> wrapper = new QueryWrapper<>();
        wrapper.eq("DOC_ID", id);
        List<SdocColname> sdocColumn = sdocColnameMapper.selectList(wrapper);
        Map<String, SdocColname> map = sdocColumn.stream()
                .collect(Collectors.toMap(SdocColname::getColumnName, a -> a, (k1, k2) -> k1));

        try {
            if ("excel".equalsIgnoreCase(docType)) {
                ExcelReader reader = ExcelUtil.getReader(docUrl);
                List<Map<String, Object>> read = reader.read(0, 1, 50);
                f1:
                for (Map<String, Object> stringObjectMap : read) {
                    line++;
                    f2:
                    for (Map.Entry<String, Object> entry : stringObjectMap.entrySet()) {
                        String k = entry.getKey();
                        String v="";
                        if(entry.getValue() != null){
                            v = entry.getValue().toString();
                        }
                        SdocColname sdocColname = map.get(k);
                        if (sdocColname != null) {
                            Integer columnLength = Integer.valueOf(sdocColname.getColumnLength());
                            int length = v.getBytes().length;
                            if (length >= columnLength) {
                                resultMap.put("status", 1);
                                resultMap.put("reason", new StringBuilder()
                                        .append(k).append("列").append(line + 1).append("行数据长度不足,请修改该字段长度").toString());
                                break f1;
                            }
                        }
                    }
                }
            } else {
                //读取文件(字符流)
                in = new BufferedReader(new InputStreamReader(new FileInputStream(docUrl), "UTF-8"));
                String[] firstLines = in.readLine().split(",");
                String str = null;
                w:
                while ((str = in.readLine()) != null) {
                    if (line >= 50) {
                        break w;
                    }
                    List<String> strings = Arrays.asList(str.split(","));
                    f:
                    for (int i = 0; i < strings.size(); i++) {
                        String firstLine = firstLines[i];
                        if (map.containsKey(firstLine)) {
                            int length = strings.get(i).getBytes().length;
                            Integer columnLength = Integer.valueOf(map.get(firstLine).getColumnLength());
                            if (length >= columnLength) {
                                resultMap.put("status", 1);

                                resultMap.put("reason", new StringBuilder()
                                        .append(firstLine).append("列").append(line).append("行数据长度不足,请修改该字段长度").toString());
                                break w;
                            }
                        }
                    }
                    str = null;
                    line++;
                }
            }
        } catch (Exception e) {
            resultMap.put("status", 0);
            resultMap.put("reason", "校验异常无法导入");
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return resultMap;
    }
}
